`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/03/08 18:32:44
// Design Name: 
// Module Name: test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module test;
//全局信号
logic ACLK;
logic ARESETn;
//写地址通道
logic AWVALID;
logic [31:0]AWADDR;
logic [7:0]AWLEN;                  //突发传输长度，实际长度为AWLEN+1
logic AWREADY;
//写数据通道
logic [63:0] WDATA;
logic WVALID;
logic [7:0] WSTRB;                //dont care
logic WLAST;
logic WREADY;
//写响应通道
logic BVALID;
logic BREADY;
logic [1:0]BRESP;
//读数据通道
logic [63:0]RDATA;
logic RVALID;
logic RREADY;
logic RLAST;
//读地址通道
logic [31:0] ARADDR;
logic [7:0] ARLEN;
logic ARVALID;
logic ARREADY;
//MEM
logic [63:0] mem [0:31];
//other signal
logic [31:0] rd_base_addr;
logic [31:0] wr_base_addr;
logic [9:0] rd_len;
logic [9:0] wr_len;
logic [9:0] rd_cnt;                     //这里的rd是相对与主机来说的，即主机读取，从机发送
logic [9:0] wr_cnt;
//initialize memory
/*initial begin
    for(int i=0;i<32;i++)
       mem[i]=i;
end*/
//ACLK,ARESET
initial begin
    ACLK=0;
    forever begin
        #5 ACLK=~ACLK;
    end
end
initial begin
    ARESETn=0;
    #10
    ARESETn=1;
end
//处理主机发起的读请求
//读地址通道
//ARREADY
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    ARREADY<=0;
else if(ARVALID&&~ARREADY)                    //ARVALID信号为1，拉高ARREADY以接受信息
    ARREADY<=1;
else if(ARVALID&&ARREADY)                     //读地址通道数据接受完毕
    ARREADY<=0;
//rd_base_addr
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    rd_base_addr<=32'd0;
else if(ARREADY&&ARVALID)
    rd_base_addr<=ARADDR;
//rd_len
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    rd_len<=0;
else if(ARVALID&&ARREADY)
    rd_len<=ARLEN;
//读数据通道
//rd_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    rd_cnt<=0;
else if(RVALID&&RREADY)                  //从机发送一个数据完成
    if(RLAST)                            //所有数据发送完毕
        rd_cnt<=0;
    else                                 //计数器加1
        rd_cnt<=rd_cnt+1;
//RVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    RVALID<=0;
else if(ARREADY&&ARVALID)                    //读地址通道结束，读数据通道开始
    RVALID<=1;
else if(RVALID&&RREADY&&RLAST)               //最后一个数据发送完成
    RVALID<=0;
//RDATA
always_comb                                  //组合逻辑，否则数据相对于发送次数延迟了一个周期
begin
if(RVALID&&RREADY)
    RDATA=mem[rd_cnt];
else
    RDATA=0;
end
//RLAST
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    RLAST<=0;
else if(rd_cnt==rd_len-1&&RVALID&&RREADY)              //rd_len等于实际长度-1
    RLAST<=1;
else
    RLAST<=0;
//处理主机发起的写请求
//写地址通道
//AWREADY
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    AWREADY<=0;
else if(AWVALID&&~AWREADY)
    AWREADY<=1;
else if(AWVALID&&AWREADY)                   //写地址通道接收信息完毕
    AWREADY<=0;
//wr_len
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    wr_len<=0;
else if(AWVALID&&AWREADY)
    wr_len<=AWLEN;
//wr_base_addr
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    wr_base_addr<=0;
else if(AWVALID&&AWREADY)
    wr_base_addr<=AWADDR;
//写数据通道
//WREADY
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
   WREADY<=0;
else if(AWVALID&&AWREADY)                  //写地址通道完成之后拉高WREADY以等待数据的到来
   WREADY<=1;
else if(WVALID&&WLAST&&WREADY)             //最后一个数据接收后拉低WREADY
   WREADY<=0;
//wr_cnt                                  //wr是相对于主机来说的，主机写数据，从机接收数据
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    wr_cnt<=0;
else if(WVALID&&WREADY)
    if(WLAST)                            //从机接受数据完成
        wr_cnt<=0;
    else 
        wr_cnt<=wr_cnt+1;
//WDATA
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
begin
    for(int i=0;i<32;i++)
        mem[i]<=i;
end
else if(WVALID&&WREADY)
    mem[wr_cnt]<=WDATA;
//写响应通道
//BVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    BVALID<=0;
else if(WVALID&&WLAST&&WREADY)
    BVALID<=1;
else if(BVALID&&BREADY&&BRESP==2'b00)
    BVALID<=0;
//BRESP
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    BRESP<=2'b11;
else if(WVALID&&WREADY&&WLAST)
    BRESP<=2'b00;
else if(BREADY&&BVALID&&BRESP==2'b00)
    BRESP<=2'b11;
//打印结果
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)
    ;
else if(BREADY&&BVALID&&BRESP==2'b00)
begin
    for(int i=0;i<32;i++)
        $display("%d",mem[i]);
end
//例化主机
PL_DDR_Test U(
//全局信号
.ACLK(ACLK),
.ARESETn(ARESETn),
//写地址通道信号
.AWVALID(AWVALID),           
.AWADDR(AWADDR),
.AWLEN(AWLEN),
.AWID(),              //dont care
.AWSIZE(),       //dont care
.AWBURST(),      //dont care
.AWLOCK(),            //dont care
.AWCACHE(),      //dont care
.AWPROT(),       //dont care
.AWQOS(),        //dont care
.AWUSER(),            //dont care
.AWREADY(AWREADY),
//写数据通道信号
.WDATA(WDATA),
.WSTRB(WSTRB),
.WLAST(WLAST),
.WUSER(),             //dont care
.WVALID(WVALID),
.WREADY(WREADY),
//写应答通道信号
.BREADY(BREADY),
.BID(),                //dont care
.BRESP(BRESP),
.BUSER(),              //dont care
.BVALID(BVALID),
//读地址通道信号
.ARID(),              //dont care
.ARADDR(ARADDR),
.ARLEN(ARLEN),
.ARSIZE(),       //dont care
.ARBURST(),      //dont care
.ARLOCK(),       //dont care
.ARCACHE(),      //dont care
.ARPROT(),       //dont care
.ARQOS(),        //dont care
.ARUSER(),            //done care
.ARVALID(ARVALID),       
.ARREADY(ARREADY),
//读数据通道
.RREADY(RREADY),
.RID(),                //dont care
.RDATA(RDATA),   
.RRESP(RRESP),         //dont care   
.RLAST(RLAST),          
.RUSER(),              //dont care
.RVALID(RVALID)
);
endmodule
